﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Senthil.Mobile.WhereAmI;

namespace wamilibtest
{
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class RouteTests
    {
        public RouteTests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestGetNextLocation()
        {
            Route route = new Route("TestRoute");

            LocationGroup lg1 = new LocationGroup("LG1");
            LocationGroup lg2 = new LocationGroup("LG2");

            route.AddLocationGroup(lg1);
            route.AddLocationGroup(lg2);

            Location l1 = route.Associate(lg1, "L1");
            Location l2 = route.Associate(lg2, "L2");

            route.AddNextRoutePoint(l1, TimeSpan.Zero);
            route.AddNextRoutePoint(l2, TimeSpan.FromSeconds(5));

            Location actualL2 = route.GetNextLocation(l1);
            Assert.AreEqual("L2", actualL2.Name);
        }

        [TestMethod]
        public void TestGetNextMajorLocationGroup()
        {
            Route route = new Route("TestRoute");

            LocationGroup lg1 = new LocationGroup("LG1", true);
            LocationGroup lg2 = new LocationGroup("LG2", true);

            route.AddLocationGroup(lg1);
            route.AddLocationGroup(lg2);

            Location l1 = route.Associate(lg1, "L1");
            Location l2 = route.Associate(lg2, "L2");

            route.AddNextRoutePoint(l1, TimeSpan.Zero);
            route.AddNextRoutePoint(l2, TimeSpan.FromSeconds(5));

            LocationGroup actualLG2 = route.GetNextMajorLocationGroup(l1);
            Assert.AreEqual(lg2, actualLG2);
        }

        [TestMethod]
        public void TestGetAverageTimeTaken()
        {
            Route route = new Route("TestRoute");

            LocationGroup lg1 = new LocationGroup("LG1", true);
            LocationGroup lg2 = new LocationGroup("LG2", true);

            route.AddLocationGroup(lg1);
            route.AddLocationGroup(lg2);

            Location l1 = route.Associate(lg1, "L1");

            Location l2 = route.Associate(lg2, "L2");
            Location l3 = route.Associate(lg2, "L3");
            Location l4 = route.Associate(lg2, "L4");

            route.AddNextRoutePoint(l1, TimeSpan.Zero);
            route.AddNextRoutePoint(l2, TimeSpan.FromSeconds(5));
            route.AddNextRoutePoint(l3, TimeSpan.FromSeconds(5));
            route.AddNextRoutePoint(l4, TimeSpan.FromSeconds(5));

            TimeSpan actual = route.GetAverageTimeTaken(l1, new List<Location>() { l2, l3, l4 });
            Assert.AreEqual(TimeSpan.FromSeconds(10), actual);
        }

        [TestMethod]
        public void TestGetAverageTimeTakenWithFromLocationBetweenToLocations()
        {
            Route route = new Route("TestRoute");

            LocationGroup lg1 = new LocationGroup("LG1", true);
            
            route.AddLocationGroup(lg1);

            Location l1 = route.Associate(lg1, "L1");
            Location l2 = route.Associate(lg1, "L2");
            Location l3 = route.Associate(lg1, "L3");
            Location l4 = route.Associate(lg1, "L4");

            route.AddNextRoutePoint(l1, TimeSpan.Zero);
            route.AddNextRoutePoint(l2, TimeSpan.FromSeconds(5));
            route.AddNextRoutePoint(l3, TimeSpan.FromSeconds(5));
            route.AddNextRoutePoint(l4, TimeSpan.FromSeconds(10));

            TimeSpan actual = route.GetAverageTimeTaken(l2, new List<Location>() { l1, l2, l3, l4 });
            Assert.AreEqual(TimeSpan.FromSeconds(10), actual);
        }

        [TestMethod]
        public void TestGetTimeSpan()
        {   
            Route route = new Route("TestRoute");

            LocationGroup lg1 = new LocationGroup("LG1", true);
            LocationGroup lg2 = new LocationGroup("LG2", true);

            route.AddLocationGroup(lg1);
            route.AddLocationGroup(lg2);

            Location l1 = route.Associate(lg1, "L1");
            Location l2 = route.Associate(lg2, "L2");

            route.AddNextRoutePoint(l1, TimeSpan.Zero);
            route.AddNextRoutePoint(l2, TimeSpan.FromSeconds(5));

            TimeSpan actualSpan = route.GetTimeTaken(l1, l2);
            Assert.AreEqual(TimeSpan.FromSeconds(5), actualSpan);
        }

        //[TestMethod]
        public void TestLoadSave()
        {
            Environment.CurrentDirectory = @"E:\";

            Route route = new Route("TestRoute");

            LocationGroup lg1 = new LocationGroup("LG1", true);
            LocationGroup lg2 = new LocationGroup("LG2", true);

            route.AddLocationGroup(lg1);
            route.AddLocationGroup(lg2);

            Location l1 = route.Associate(lg1, "L1");
            Location l2 = route.Associate(lg2, "L2");

            route.AddNextRoutePoint(l1, TimeSpan.Zero);
            route.AddNextRoutePoint(l2, TimeSpan.FromSeconds(5));

            RouteManager.AddRoute(route);
            RouteManager.Save();
            RouteManager.LoadAllRoutes();

            Assert.AreEqual(1, RouteManager.Routes.Count());

            route = RouteManager.Routes.First();

            LocationGroup[] groups = route.LocationGroups;
            Assert.AreEqual(2, groups.Count());

            Assert.AreEqual("LG1", groups[0].Name);
            Assert.AreEqual("LG2", groups[1].Name);

            Assert.AreEqual(true, groups[0].IsSpecial);
            Assert.AreEqual(true, groups[1].IsSpecial);

            Location[] locations = groups[0].Locations;
            Assert.AreEqual(l1, locations[0]);

            locations = groups[1].Locations;
            Assert.AreEqual(l2, locations[0]);
        }
    }
}
